//solver class

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class solver
{
   puzzle the_puzzle = new puzzle();
   public puzzle_piece ppiece0;
   public puzzle_piece ppiece1;
   public puzzle_piece ppiece2;
   public puzzle_piece ppiece3;
   public puzzle_piece ppiece4;
   public puzzle_piece ppiece5;
   public puzzle_piece ppiece6;
   public puzzle_piece ppiece7;
   public puzzle_piece ppiece8;
   public puzzle_piece ppiece9;
   public puzzle_piece ppiece10;
   public puzzle_piece ppiece11;
   public puzzle_piece ppiece12;
   public puzzle_piece ppiece13;
   public puzzle_piece ppiece14;
   public puzzle_piece ppiece15;
        
    public solver()
    {
       //left top right bot
       //picture goes from top left to bottom right
       System.out.println("Initializing...");
        ppiece0 = new puzzle_piece(8, 6, 3, 1, 1);
        ppiece1 = new puzzle_piece(6, 6, 7, 2, 2);
        ppiece2 = new puzzle_piece(7, 8, 4, 7, 3);
        ppiece3 = new puzzle_piece(8, 6, 1, 2, 4);
       
        ppiece4 = new puzzle_piece(7,6,1,2, 5);
        ppiece5 = new puzzle_piece(6,5,2,4, 6);
        ppiece6 = new puzzle_piece(5,7,4,2, 7);
        ppiece7 = new puzzle_piece(8,5,2,4, 8);
       
        ppiece8 = new puzzle_piece(7,5,3,1, 9);
        ppiece9 = new puzzle_piece(7,8,4,1, 10);
        ppiece10 = new puzzle_piece(8,5,3,4, 11);
        ppiece11 = new puzzle_piece(7,8,2,2, 12);
       
        ppiece12 = new puzzle_piece(6,6,4,3, 13);
        ppiece13 = new puzzle_piece(8,6,4,3, 14);
        ppiece14 = new puzzle_piece(8,8,2,4, 15);
        ppiece15 = new puzzle_piece(5,5,1,4, 16);
       System.out.println("Done.");
       System.out.println("Solving...");
      
       int i = 0;
       String solution = "";
       puzzle_piece[] pieces = new puzzle_piece[16];
      
       while(!the_puzzle.is_solved())
       {
           pieces = shuffle();
           
           
           if (!the_puzzle.solve(pieces[0], pieces[1], pieces[2], pieces[3], pieces[4], pieces[5], pieces[6], 
           pieces[7], pieces[8], pieces[9], pieces[10], pieces[11], pieces[12], pieces[13], pieces[14], pieces[15]))
           { 
               System.out.println("Puzzle not solved."); 
           }
           i++;
           System.out.println("--------------------------------------------------------Iteration "+i+" Highschore: "+the_puzzle.highscore); 
           solution = ""+
           pieces[0].piece_num+" "+
           pieces[1].piece_num+" "+
           pieces[2].piece_num+" "+
           pieces[3].piece_num+" "+
           pieces[4].piece_num+" "+
           pieces[5].piece_num+" "+
           pieces[6].piece_num+" "+
           pieces[7].piece_num+" "+
           pieces[8].piece_num+" "+
           pieces[9].piece_num+" "+
           pieces[10].piece_num+" "+
           pieces[11].piece_num+" "+
           pieces[12].piece_num+" "+
           pieces[13].piece_num+" "+
           pieces[14].piece_num+" "+
           pieces[15].piece_num+ ".";
           
           System.out.println("Puzzle solution: " + solution);
       }
      
       
        
       
        
        
       System.out.println("Puzzle solved after "+i+" iterations.");
       //returns the order of puzzle pieces
       System.out.println("Puzzle solution: " + solution);
       
    }
    
    public puzzle_piece[] shuffle()
    {
        //shuffles the pieces around by creating a list of numbers 0-15 non repeating
        //and setting an array of puzzle pieces to the shuffled list of old puzzle pieces
        puzzle_piece[] pieces = new puzzle_piece[16];
        ArrayList<Integer> indices = new ArrayList<Integer>();
        Integer[] a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        List<Integer> nums = new ArrayList<Integer>(Arrays.asList(a));
        for(Integer i : a) {
            Integer num = nums.remove((int)(Math.random() * nums.size()));
            //System.out.println("random value: " + num);
            indices.add(num);
        }

        int number;
        pieces[indices.get(0)] = ppiece0;
        number = (int)(Math.random() * 4);
        ppiece0.rotate(number);
        
        pieces[indices.get(1)] = ppiece1;
        number = ((int)(Math.random() * 4));
        ppiece1.rotate(number);
        
        pieces[indices.get(2)] = ppiece2;
        number = ((int)(Math.random() * 4));
        ppiece2.rotate(number);
        pieces[indices.get(3)] = ppiece3;
        number = ((int)(Math.random() * 4));
        ppiece3.rotate(number);
        pieces[indices.get(4)] = ppiece4;
        number = ((int)(Math.random() * 4));
        ppiece4.rotate(number);
        pieces[indices.get(5)] = ppiece5;
        number = ((int)(Math.random() * 4));
        ppiece5.rotate(number);
        pieces[indices.get(6)] = ppiece6;
        number = ((int)(Math.random() * 4));
        ppiece6.rotate(number);
        pieces[indices.get(7)] = ppiece7;
        number = ((int)(Math.random() * 4));
        ppiece7.rotate(number);
        pieces[indices.get(8)] = ppiece8;
        number = ((int)(Math.random() * 4));
        ppiece8.rotate(number);
        
        pieces[indices.get(9)] = ppiece9;
        number = ((int)(Math.random() * 4));
        ppiece9.rotate(number);
        
        pieces[indices.get(10)] = ppiece10;
        number = ((int)(Math.random() * 4));
        ppiece10.rotate(number);
        
        pieces[indices.get(11)] = ppiece11;
        number = ((int)(Math.random() * 4));
        ppiece11.rotate(number);
        
        pieces[indices.get(12)] = ppiece12;
        number = ((int)(Math.random() * 4));
        ppiece12.rotate(number);
        
        pieces[indices.get(13)] = ppiece13;
        number = ((int)(Math.random() * 4));
        ppiece13.rotate(number);
        
        pieces[indices.get(14)] = ppiece14;
        number = ((int)(Math.random() * 4));
        ppiece14.rotate(number);
        
        pieces[indices.get(15)] = ppiece15;
        number = ((int)(Math.random() * 4));
        ppiece15.rotate(number);
        
        
        return pieces;
    }


}
